<!DOCTYPE html><html><head>
      <title>readme</title>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      
      <link rel="stylesheet" href="file:///c:\Users\southwind\.vscode\extensions\shd101wyy.markdown-preview-enhanced-0.8.15\crossnote\dependencies\katex\katex.min.css">
      
      
      
      
      
      <style>
      code[class*=language-],pre[class*=language-]{color:#333;background:0 0;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.4;-moz-tab-size:8;-o-tab-size:8;tab-size:8;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:.8em;overflow:auto;border-radius:3px;background:#f5f5f5}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal;background:#f5f5f5}.token.blockquote,.token.comment{color:#969896}.token.cdata{color:#183691}.token.doctype,.token.macro.property,.token.punctuation,.token.variable{color:#333}.token.builtin,.token.important,.token.keyword,.token.operator,.token.rule{color:#a71d5d}.token.attr-value,.token.regex,.token.string,.token.url{color:#183691}.token.atrule,.token.boolean,.token.code,.token.command,.token.constant,.token.entity,.token.number,.token.property,.token.symbol{color:#0086b3}.token.prolog,.token.selector,.token.tag{color:#63a35c}.token.attr-name,.token.class,.token.class-name,.token.function,.token.id,.token.namespace,.token.pseudo-class,.token.pseudo-element,.token.url-reference .token.variable{color:#795da3}.token.entity{cursor:help}.token.title,.token.title .token.punctuation{font-weight:700;color:#1d3e81}.token.list{color:#ed6a43}.token.inserted{background-color:#eaffea;color:#55a532}.token.deleted{background-color:#ffecec;color:#bd2c00}.token.bold{font-weight:700}.token.italic{font-style:italic}.language-json .token.property{color:#183691}.language-markup .token.tag .token.punctuation{color:#333}.language-css .token.function,code.language-css{color:#0086b3}.language-yaml .token.atrule{color:#63a35c}code.language-yaml{color:#183691}.language-ruby .token.function{color:#333}.language-markdown .token.url{color:#795da3}.language-makefile .token.symbol{color:#795da3}.language-makefile .token.variable{color:#183691}.language-makefile .token.builtin{color:#0086b3}.language-bash .token.keyword{color:#0086b3}pre[data-line]{position:relative;padding:1em 0 1em 3em}pre[data-line] .line-highlight-wrapper{position:absolute;top:0;left:0;background-color:transparent;display:block;width:100%}pre[data-line] .line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}pre[data-line] .line-highlight:before,pre[data-line] .line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}pre[data-line] .line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}html body{font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line-height:1.6;color:#333;background-color:#fff;overflow:initial;box-sizing:border-box;word-wrap:break-word}html body>:first-child{margin-top:0}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{line-height:1.2;margin-top:1em;margin-bottom:16px;color:#000}html body h1{font-size:2.25em;font-weight:300;padding-bottom:.3em}html body h2{font-size:1.75em;font-weight:400;padding-bottom:.3em}html body h3{font-size:1.5em;font-weight:500}html body h4{font-size:1.25em;font-weight:600}html body h5{font-size:1.1em;font-weight:600}html body h6{font-size:1em;font-weight:600}html body h1,html body h2,html body h3,html body h4,html body h5{font-weight:600}html body h5{font-size:1em}html body h6{color:#5c5c5c}html body strong{color:#000}html body del{color:#5c5c5c}html body a:not([href]){color:inherit;text-decoration:none}html body a{color:#08c;text-decoration:none}html body a:hover{color:#00a3f5;text-decoration:none}html body img{max-width:100%}html body>p{margin-top:0;margin-bottom:16px;word-wrap:break-word}html body>ol,html body>ul{margin-bottom:16px}html body ol,html body ul{padding-left:2em}html body ol.no-list,html body ul.no-list{padding:0;list-style-type:none}html body ol ol,html body ol ul,html body ul ol,html body ul ul{margin-top:0;margin-bottom:0}html body li{margin-bottom:0}html body li.task-list-item{list-style:none}html body li>p{margin-top:0;margin-bottom:0}html body .task-list-item-checkbox{margin:0 .2em .25em -1.8em;vertical-align:middle}html body .task-list-item-checkbox:hover{cursor:pointer}html body blockquote{margin:16px 0;font-size:inherit;padding:0 15px;color:#5c5c5c;background-color:#f0f0f0;border-left:4px solid #d6d6d6}html body blockquote>:first-child{margin-top:0}html body blockquote>:last-child{margin-bottom:0}html body hr{height:4px;margin:32px 0;background-color:#d6d6d6;border:0 none}html body table{margin:10px 0 15px 0;border-collapse:collapse;border-spacing:0;display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}html body table th{font-weight:700;color:#000}html body table td,html body table th{border:1px solid #d6d6d6;padding:6px 13px}html body dl{padding:0}html body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}html body dl dd{padding:0 16px;margin-bottom:16px}html body code{font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-size:.85em;color:#000;background-color:#f0f0f0;border-radius:3px;padding:.2em 0}html body code::after,html body code::before{letter-spacing:-.2em;content:'\00a0'}html body pre>code{padding:0;margin:0;word-break:normal;white-space:pre;background:0 0;border:0}html body .highlight{margin-bottom:16px}html body .highlight pre,html body pre{padding:1em;overflow:auto;line-height:1.45;border:#d6d6d6;border-radius:3px}html body .highlight pre{margin-bottom:0;word-break:normal}html body pre code,html body pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}html body pre code:after,html body pre code:before,html body pre tt:after,html body pre tt:before{content:normal}html body blockquote,html body dl,html body ol,html body p,html body pre,html body ul{margin-top:0;margin-bottom:16px}html body kbd{color:#000;border:1px solid #d6d6d6;border-bottom:2px solid #c7c7c7;padding:2px 4px;background-color:#f0f0f0;border-radius:3px}@media print{html body{background-color:#fff}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{color:#000;page-break-after:avoid}html body blockquote{color:#5c5c5c}html body pre{page-break-inside:avoid}html body table{display:table}html body img{display:block;max-width:100%;max-height:100%}html body code,html body pre{word-wrap:break-word;white-space:pre}}.markdown-preview{width:100%;height:100%;box-sizing:border-box}.markdown-preview ul{list-style:disc}.markdown-preview ul ul{list-style:circle}.markdown-preview ul ul ul{list-style:square}.markdown-preview ol{list-style:decimal}.markdown-preview ol ol,.markdown-preview ul ol{list-style-type:lower-roman}.markdown-preview ol ol ol,.markdown-preview ol ul ol,.markdown-preview ul ol ol,.markdown-preview ul ul ol{list-style-type:lower-alpha}.markdown-preview .newpage,.markdown-preview .pagebreak{page-break-before:always}.markdown-preview pre.line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}.markdown-preview pre.line-numbers>code{position:relative}.markdown-preview pre.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:1em;font-size:100%;left:0;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-preview pre.line-numbers .line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.markdown-preview pre.line-numbers .line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.markdown-preview .mathjax-exps .MathJax_Display{text-align:center!important}.markdown-preview:not([data-for=preview]) .code-chunk .code-chunk-btn-group{display:none}.markdown-preview:not([data-for=preview]) .code-chunk .status{display:none}.markdown-preview:not([data-for=preview]) .code-chunk .output-div{margin-bottom:16px}.markdown-preview .md-toc{padding:0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link div,.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link p{display:inline}.markdown-preview .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}.scrollbar-style::-webkit-scrollbar{width:8px}.scrollbar-style::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}.scrollbar-style::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,.66);border:4px solid rgba(150,150,150,.66);background-clip:content-box}html body[for=html-export]:not([data-presentation-mode]){position:relative;width:100%;height:100%;top:0;left:0;margin:0;padding:0;overflow:auto}html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{position:relative;top:0;min-height:100vh}@media screen and (min-width:914px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{padding:2em calc(50% - 457px + 2em)}}@media screen and (max-width:914px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{font-size:14px!important;padding:1em}}@media print{html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn{display:none}}html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn{position:fixed;bottom:8px;left:8px;font-size:28px;cursor:pointer;color:inherit;z-index:99;width:32px;text-align:center;opacity:.4}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] #sidebar-toc-btn{opacity:1}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc{position:fixed;top:0;left:0;width:300px;height:100%;padding:32px 0 48px 0;font-size:14px;box-shadow:0 0 4px rgba(150,150,150,.33);box-sizing:border-box;overflow:auto;background-color:inherit}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar{width:8px}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,.66);border:4px solid rgba(150,150,150,.66);background-clip:content-box}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc a{text-decoration:none}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc{padding:0 16px}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link div,html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link p{display:inline}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{left:300px;width:calc(100% - 300px);padding:2em calc(50% - 457px - 300px / 2);margin:0;box-sizing:border-box}@media screen and (max-width:1274px){html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{width:100%}}html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .markdown-preview{left:50%;transform:translateX(-50%)}html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .md-sidebar-toc{display:none}
/* Please visit the URL below for more information: */
/*   https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */

      </style>
      <!-- The content below will be included at the end of the <head> element. --><script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function () {
    // your code here
  });
</script></head><body for="html-export">
    
    
      <div class="crossnote markdown-preview  ">
      
<h1 id="基于pyqt5的考试签到系统">基于pyqt5的考试签到系统 </h1>
<h2 id="论文技巧">论文技巧 </h2>
<hr>
<h3 id="一-论文结构布局建议"><strong>一、论文结构布局建议</strong> </h3>
<h4 id="1-摘要300-500字"><strong>1. 摘要（300-500字）</strong> </h4>
<ul>
<li><strong>内容</strong>：简要说明系统目标（解决传统签到效率低、易代签的问题）、技术选型（PyQt5、face_recognition、MySQL）、核心功能（人脸识别签到、考试管理）。</li>
<li><strong>关键词</strong>：人脸识别、PyQt5、MySQL、考试签到系统。</li>
</ul>
<hr>
<h4 id="2-引言"><strong>2. 引言</strong> </h4>
<ul>
<li><strong>背景与意义</strong>：传统签到方式弊端（代签、效率低），人脸识别的技术优势。</li>
<li><strong>国内外现状</strong>：引用2-3篇相关论文，对比现有签到系统。</li>
<li><strong>本文工作</strong>：说明系统创新点（如结合考试管理与实时人脸验证）。</li>
</ul>
<hr>
<h4 id="3-系统分析"><strong>3. 系统分析</strong> </h4>
<ul>
<li><strong>需求分析</strong>
<ul>
<li>功能需求：教师发布考试、学生人脸签到、签到记录管理。</li>
<li>非功能需求：实时性（识别速度≤10秒）。</li>
</ul>
</li>
<li><strong>可行性分析</strong>
<ul>
<li>技术可行性：Python生态成熟，face_recognition库开源。</li>
<li>经济可行性：低成本（无需专用硬件）。</li>
</ul>
</li>
</ul>
<hr>
<h4 id="4-系统设计核心章节"><strong>4. 系统设计（核心章节）</strong> </h4>
<ul>
<li>
<p><strong>架构设计</strong></p>
<ul>
<li>分层架构：展示层（PyQt5 UI）、业务层（人脸识别逻辑）、数据层（MySQL）。</li>
<li>技术栈图：绘制PyQt5+Python+MySQL的技术关联图。</li>
</ul>
</li>
<li>
<p><strong>功能模块设计</strong></p>
<ul>
<li>教师模块：考试发布、签到数据导出（Excel）。</li>
<li>学生模块：考试列表展示、摄像头调用、人脸比对。</li>
</ul>
</li>
<li>
<p><strong>数据库设计</strong></p>
<ul>
<li><strong>E-R图设计</strong>（重点）：
<ul>
<li><strong>实体</strong>：教师（teacher_users, 工号）、学生（student_users, 学号）、考试（exam_schedule）、签到记录（exam_record）、班级（class_info），括号里面第二个是组建，若我没有写出就是自增。</li>
<li><strong>关系</strong>：教师-考试（1:N）、学生-考试（M:N）。</li>
<li><strong>工具推荐</strong>：iodraw绘制，标注主外键(你画的时候联系我)。</li>
</ul>
</li>
<li><strong>表结构设计</strong>：
<ul>
<li><code>students</code>表：存储人脸（LongBLOB类型加密,BLOB支持的图片大小不够）。</li>
</ul>
</li>
<li><strong>范式说明</strong>：满足第三范式（消除传递依赖，如考试地点独立成表）。</li>
</ul>
</li>
<li>
<p><strong>界面设计</strong></p>
<ul>
<li>教师端：考试发布表单（日期选择器、地点下拉框）。</li>
<li>学生端：签到按钮与实时摄像头画面嵌入（使用OpenCV的VideoCapture）。</li>
</ul>
</li>
</ul>
<hr>
<h4 id="5-系统实现技术重点章节"><strong>5. 系统实现（技术重点章节）</strong> </h4>
<ul>
<li>
<p><strong>技术选型详解</strong></p>
<ul>
<li><strong>PyQt5</strong>：说明信号槽机制实现UI交互（如点击签到触发摄像头）。</li>
<li><strong>face_recognition</strong>：
<ul>
<li>流程：face_locations()定位人脸→compare_faces()比对编码（阈值0.5）。</li>
<li>性能优化：使用HOG模式替代CNN以提升速度。</li>
</ul>
</li>
<li><strong>pymysql</strong>：连接池配置（避免频繁创建连接），防SQL注入措施。</li>
</ul>
</li>
<li>
<p><strong>核心代码片段</strong></p>
<ul>
<li>人脸识别代码示例：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token comment"># 加载学生预存的人脸编码</span>
known_face <span class="token operator">=</span> face_recognition<span class="token punctuation">.</span>load_image_file<span class="token punctuation">(</span><span class="token string">"student.jpg"</span><span class="token punctuation">)</span>
known_encoding <span class="token operator">=</span> face_recognition<span class="token punctuation">.</span>face_encodings<span class="token punctuation">(</span>known_face<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>

<span class="token comment"># 实时捕获并比对</span>
video_capture <span class="token operator">=</span> cv2<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token keyword keyword-while">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> video_capture<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
    face_locations <span class="token operator">=</span> face_recognition<span class="token punctuation">.</span>face_locations<span class="token punctuation">(</span>frame<span class="token punctuation">)</span>
    <span class="token keyword keyword-if">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>face_locations<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">:</span>
        show_error<span class="token punctuation">(</span><span class="token string">"未检测到人脸！"</span><span class="token punctuation">)</span>
    <span class="token keyword keyword-else">else</span><span class="token punctuation">:</span>
        current_encoding <span class="token operator">=</span> face_recognition<span class="token punctuation">.</span>face_encodings<span class="token punctuation">(</span>frame<span class="token punctuation">,</span> face_locations<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
        matches <span class="token operator">=</span> face_recognition<span class="token punctuation">.</span>compare_faces<span class="token punctuation">(</span><span class="token punctuation">[</span>known_encoding<span class="token punctuation">]</span><span class="token punctuation">,</span> current_encoding<span class="token punctuation">,</span> tolerance<span class="token operator">=</span><span class="token number">0.5</span><span class="token punctuation">)</span>
</code></pre></li>
</ul>
</li>
<li>
<p><strong>难点解决方案</strong></p>
<ul>
<li>多线程处理：摄像头采集与UI响应分离（QThread）。</li>
<li>光照适应：Gamma校正预处理图像。</li>
</ul>
</li>
</ul>
<hr>
<h4 id="6-系统测试"><strong>6. 系统测试</strong> </h4>
<ul>
<li><strong>测试用例设计</strong>
<ul>
<li>功能测试：测试非本人是否能够登录、测试各个功能是否正常。</li>
</ul>
</li>
<li><strong>测试结果</strong>
<ul>
<li>准确率：统计100次测试的误识率（FRR/FAR）。</li>
</ul>
</li>
</ul>
<hr>
<h4 id="7-总结与展望"><strong>7. 总结与展望</strong> </h4>
<ul>
<li><strong>成果总结</strong>：签到成功率≥95%。</li>
<li><strong>不足与改进</strong>：移动端适配、活体检测（防止照片攻击,这一点你得自己考虑写不写进去）。</li>
</ul>
<hr>
<h4 id="8-参考文献"><strong>8. 参考文献</strong> </h4>
<ul>
<li>必引文献：
<ul>
<li>face_recognition官方文档（<a href="https://github.com/ageitgey/face_recognition%EF%BC%89">https://github.com/ageitgey/face_recognition）</a></li>
<li>MySQL 8.0性能优化指南（ISBN示例）。</li>
<li>PyQt5图形界面开发实战（书籍或博文）。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="二-技术侧重点与写作技巧"><strong>二、技术侧重点与写作技巧</strong> </h3>
<ol>
<li><strong>数据库设计</strong>
<ul>
<li>详细说明为何使用InnoDB引擎（支持事务）。</li>
</ul>
</li>
<li><strong>人脸识别</strong>
<ul>
<li>face_recognition。</li>
</ul>
</li>
</ol>
<hr>
<h3 id="三-工具推荐"><strong>三、工具推荐</strong> </h3>
<ul>
<li><strong>绘图工具</strong>：E-R图用iodraw（免费）。</li>
<li><strong>文档管理</strong>：使用Markdown编写，Vscode实时预览。</li>
<li><strong>版本控制</strong>：GitHub托管代码，可以显示是你自己做的。</li>
</ul>
<hr>
<h2 id="技术简介">技术简介 </h2>
<hr>
<h3 id="1-python"><strong>1. Python</strong> </h3>
<h4 id="核心概念"><strong>核心概念</strong> </h4>
<ul>
<li><strong>解释型语言</strong>：无需编译，直接运行（适合快速开发）。</li>
<li><strong>动态类型</strong>：变量无需声明类型，灵活性高。</li>
<li><strong>丰富的库生态</strong>：如<code>face_recognition</code>、<code>pymysql</code>等。</li>
</ul>
<h4 id="项目应用"><strong>项目应用</strong> </h4>
<ul>
<li><strong>系统开发语言</strong>：用于逻辑控制（人脸识别）、数据库交互（pymysql）、界面开发（PyQt5）。</li>
<li><strong>优势</strong>：代码简洁，适合快速实现复杂功能（如人脸比对）。</li>
</ul>
<hr>
<h3 id="2-python面向对象编程oop"><strong>2. Python面向对象编程（OOP）</strong> </h3>
<h4 id="核心概念-1"><strong>核心概念</strong> </h4>
<ul>
<li><strong>类与对象</strong>：例如在系统中定义<code>Teacher</code>类（属性：教师ID、姓名；方法：发布考试）。</li>
<li><strong>三大特性</strong>：
<ul>
<li><strong>封装</strong>：隐藏数据细节（如学生人脸编码存储在私有属性中）。</li>
<li><strong>继承</strong>：创建<code>User</code>基类，<code>Student</code>和<code>Teacher</code>继承其通用属性（如账号、密码）。</li>
<li><strong>多态</strong>：不同用户登录后显示不同界面（通过重写基类方法）。</li>
</ul>
</li>
</ul>
<h4 id="项目应用-1"><strong>项目应用</strong> </h4>
<ul>
<li><strong>代码结构优化</strong>：通过OOP将系统拆分为模块（如<code>ExamManager</code>、<code>FaceRecognizer</code>类）。</li>
<li><strong>示例代码</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-class">class</span> <span class="token class-name">Student</span><span class="token punctuation">:</span>
    <span class="token keyword keyword-def">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> student_id<span class="token punctuation">,</span> face_encoding<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>student_id <span class="token operator">=</span> student_id
        self<span class="token punctuation">.</span>__face_encoding <span class="token operator">=</span> face_encoding  <span class="token comment"># 私有属性，封装人脸数据</span>

    <span class="token keyword keyword-def">def</span> <span class="token function">get_face_encoding</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword keyword-return">return</span> self<span class="token punctuation">.</span>__face_encoding  <span class="token comment"># 通过方法暴露数据</span>
</code></pre></li>
</ul>
<hr>
<h3 id="3-pyqt5"><strong>3. PyQt5</strong> </h3>
<h4 id="核心概念-2"><strong>核心概念</strong> </h4>
<ul>
<li><strong>跨平台GUI框架</strong>：基于Qt库，支持Windows、Linux、macOS。</li>
<li><strong>信号与槽机制</strong>：实现事件驱动（如点击按钮触发签到逻辑）。</li>
</ul>
<h4 id="项目应用-2"><strong>项目应用</strong> </h4>
<ul>
<li><strong>界面开发</strong>：
<ul>
<li>教师端：使用<code>QTableWidget</code>展示考试列表。</li>
<li>学生端：嵌入<code>QLabel</code>显示摄像头画面（通过OpenCV捕获视频流）。</li>
</ul>
</li>
<li><strong>关键代码</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-from">from</span> PyQt5<span class="token punctuation">.</span>QtWidgets <span class="token keyword keyword-import">import</span> QPushButton
<span class="token comment"># 创建签到按钮并绑定事件</span>
btn_sign <span class="token operator">=</span> QPushButton<span class="token punctuation">(</span><span class="token string">"点击签到"</span><span class="token punctuation">,</span> parent_window<span class="token punctuation">)</span>
btn_sign<span class="token punctuation">.</span>clicked<span class="token punctuation">.</span>connect<span class="token punctuation">(</span>start_face_recognition<span class="token punctuation">)</span>  <span class="token comment"># 信号与槽连接</span>
</code></pre></li>
</ul>
<hr>
<h3 id="4-css"><strong>4. CSS</strong> </h3>
<p>后面有详细解释</p>
<hr>
<h3 id="5-pyqt5使用css"><strong>5. PyQt5使用CSS</strong> </h3>
<h4 id="实现方式"><strong>实现方式</strong> </h4>
<ul>
<li><strong>直接设置样式</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code>btn_sign<span class="token punctuation">.</span>setStyleSheet<span class="token punctuation">(</span><span class="token string">"QPushButton { color: white; }"</span><span class="token punctuation">)</span>
</code></pre></li>
<li><strong>加载外部CSS文件</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-with">with</span> <span class="token builtin">open</span><span class="token punctuation">(</span><span class="token string">"style.css"</span><span class="token punctuation">,</span> <span class="token string">"r"</span><span class="token punctuation">)</span> <span class="token keyword keyword-as">as</span> f<span class="token punctuation">:</span>
    app<span class="token punctuation">.</span>setStyleSheet<span class="token punctuation">(</span>f<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 全局应用样式</span>
</code></pre></li>
</ul>
<h4 id="项目应用-3"><strong>项目应用</strong> </h4>
<ul>
<li><strong>统一界面风格</strong>：通过CSS文件管理所有控件的样式，提升代码可维护性。</li>
</ul>
<hr>
<h3 id="6-pymysql"><strong>6. pymysql</strong> </h3>
<h4 id="核心概念-3"><strong>核心概念</strong> </h4>
<ul>
<li><strong>MySQL连接库</strong>：用于Python与MySQL数据库交互。</li>
<li><strong>关键操作</strong>：
<ul>
<li><strong>连接数据库</strong>：<code>pymysql.connect(host, user, password, database)</code></li>
<li><strong>执行SQL语句</strong>：通过<code>cursor.execute()</code>插入、查询数据。</li>
</ul>
</li>
</ul>
<h4 id="项目应用-4"><strong>项目应用</strong> </h4>
<ul>
<li><strong>数据持久化</strong>：
<ul>
<li>存储考试信息、学生人脸编码（BLOB类型）、签到记录。</li>
<li><strong>防SQL注入</strong>：使用参数化查询：<pre data-role="codeBlock" data-info="python" class="language-python python"><code>cursor<span class="token punctuation">.</span>execute<span class="token punctuation">(</span><span class="token string">"INSERT INTO students (id, name) VALUES (%s, %s)"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>student_id<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></li>
</ul>
</li>
</ul>
<hr>
<h3 id="7-单例模式singleton-pattern"><strong>7. 单例模式（Singleton Pattern）</strong> </h3>
<h4 id="核心概念-4"><strong>核心概念</strong> </h4>
<ul>
<li><strong>设计模式</strong>：确保一个类仅有一个实例，并提供全局访问点。</li>
<li><strong>实现方式</strong>（Python示例）：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-class">class</span> <span class="token class-name">DatabaseConnection</span><span class="token punctuation">:</span>
    _instance <span class="token operator">=</span> <span class="token boolean">None</span>

    <span class="token keyword keyword-def">def</span> <span class="token function">__new__</span><span class="token punctuation">(</span>cls<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword keyword-if">if</span> <span class="token keyword keyword-not">not</span> cls<span class="token punctuation">.</span>_instance<span class="token punctuation">:</span>
            cls<span class="token punctuation">.</span>_instance <span class="token operator">=</span> <span class="token builtin">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>__new__<span class="token punctuation">(</span>cls<span class="token punctuation">)</span>
            cls<span class="token punctuation">.</span>_instance<span class="token punctuation">.</span>connection <span class="token operator">=</span> pymysql<span class="token punctuation">.</span>connect<span class="token punctuation">(</span>host<span class="token operator">=</span><span class="token string">'localhost'</span><span class="token punctuation">,</span> user<span class="token operator">=</span><span class="token string">'root'</span><span class="token punctuation">,</span> password<span class="token operator">=</span><span class="token string">'123456'</span><span class="token punctuation">)</span>
        <span class="token keyword keyword-return">return</span> cls<span class="token punctuation">.</span>_instance

<span class="token comment"># 使用示例</span>
db1 <span class="token operator">=</span> DatabaseConnection<span class="token punctuation">(</span><span class="token punctuation">)</span>
db2 <span class="token operator">=</span> DatabaseConnection<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword keyword-print">print</span><span class="token punctuation">(</span>db1 <span class="token keyword keyword-is">is</span> db2<span class="token punctuation">)</span>  <span class="token comment"># 输出 True，证明是同一实例</span>
</code></pre></li>
</ul>
<h4 id="项目应用-5"><strong>项目应用</strong> </h4>
<ul>
<li><strong>数据库连接池</strong>：避免频繁创建连接，提升性能。</li>
<li><strong>配置管理类</strong>：全局统一读取配置文件。</li>
</ul>
<h4 id="优势"><strong>优势</strong> </h4>
<ul>
<li><strong>资源节约</strong>：避免重复创建对象（如数据库连接）。</li>
<li><strong>数据一致性</strong>：所有操作共享同一实例，防止状态冲突。</li>
</ul>
<hr>
<h3 id="8-css层叠样式表"><strong>8. CSS（层叠样式表）</strong> </h3>
<h4 id="css基础"><strong>CSS基础</strong> </h4>
<h5 id="1-css的作用"><strong>1. CSS的作用</strong> </h5>
<ul>
<li><strong>美化页面</strong>：控制元素的颜色、字体、布局等视觉效果。</li>
<li><strong>结构与样式分离</strong>：HTML负责内容，CSS负责样式，提高代码可维护性。</li>
</ul>
<h5 id="2-基本语法"><strong>2. 基本语法</strong> </h5>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token selector">选择器</span> <span class="token punctuation">{</span>
  <span class="token property">属性</span><span class="token punctuation">:</span> 值<span class="token punctuation">;</span>
  <span class="token property">属性</span><span class="token punctuation">:</span> 值<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>示例</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token comment">/* 将所有段落文字设为红色 */</span>
<span class="token selector">p</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token color">red</span><span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token number">16</span><span class="token unit">px</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><hr>
<h4 id="盒子模型box-model"><strong>盒子模型（Box Model）</strong> </h4>
<h5 id="1-什么是盒子模型"><strong>1. 什么是盒子模型？</strong> </h5>
<ul>
<li>
<p><strong>核心概念</strong>：每个HTML元素都被视为一个矩形盒子，由4个部分组成：</p>
<ul>
<li><strong>内容（Content）</strong>：元素的实际内容（如文本、图片）。</li>
<li><strong>内边距（Padding）</strong>：内容与边框之间的空白区域。</li>
<li><strong>边框（Border）</strong>：盒子的边界线。</li>
<li><strong>外边距（Margin）</strong>：盒子与其他元素之间的空白区域。</li>
</ul>
<p><img src="https://p-blog.csdn.net/images/p_blog_csdn_net/hjue/0cc359412cf249f55d7055f5f73a9753.gif" alt="盒子模型示意图"></p>
</li>
</ul>
<h5 id="2-盒子模型属性"><strong>2. 盒子模型属性</strong> </h5>
<table>
<thead>
<tr>
<th>属性</th>
<th>作用</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>width</code></td>
<td>内容区域的宽度</td>
<td><code>width: 200px;</code></td>
</tr>
<tr>
<td><code>height</code></td>
<td>内容区域的高度</td>
<td><code>height: 100px;</code></td>
</tr>
<tr>
<td><code>padding</code></td>
<td>内边距</td>
<td><code>padding: 10px 20px;</code></td>
</tr>
<tr>
<td><code>border</code></td>
<td>边框</td>
<td><code>border: 1px solid #000;</code></td>
</tr>
<tr>
<td><code>margin</code></td>
<td>外边距</td>
<td><code>margin: 20px auto;</code></td>
</tr>
</tbody>
</table>
<h5 id="3-盒子大小计算"><strong>3. 盒子大小计算</strong> </h5>
<ul>
<li><strong>默认行为</strong>：元素的最终宽度/高度 = <code>width/height + padding + border</code>。</li>
<li><strong><code>box-sizing</code> 属性</strong>：
<ul>
<li><code>content-box</code>（默认）：按上述公式计算。</li>
<li><code>border-box</code>：宽度/高度包含 <code>padding</code> 和 <code>border</code>（更符合直觉）。</li>
</ul>
</li>
</ul>
<p><strong>示例</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token comment">/* 更推荐使用 border-box */</span>
<span class="token selector">div</span> <span class="token punctuation">{</span>
  <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">200</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">20</span><span class="token unit">px</span><span class="token punctuation">;</span> <span class="token comment">/* 此时总宽度仍为200px */</span>
<span class="token punctuation">}</span>
</code></pre><h5 id="4-应用场景pyqt5项目示例"><strong>4. 应用场景（PyQt5项目示例）</strong> </h5>
<ul>
<li><strong>按钮美化</strong>：<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token selector">QPushButton</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">8</span><span class="token unit">px</span> <span class="token number">16</span><span class="token unit">px</span><span class="token punctuation">;</span>      <span class="token comment">/* 内边距 */</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> <span class="token number">10</span><span class="token unit">px</span><span class="token punctuation">;</span>           <span class="token comment">/* 外边距 */</span>
  <span class="token property">border</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token unit">px</span> solid <span class="token hexcode color">#4CAF50</span><span class="token punctuation">;</span> <span class="token comment">/* 边框 */</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token number">5</span><span class="token unit">px</span><span class="token punctuation">;</span>     <span class="token comment">/* 圆角 */</span>
<span class="token punctuation">}</span>
</code></pre></li>
</ul>
<hr>
<h4 id="flex布局弹性布局"><strong>Flex布局（弹性布局）</strong> </h4>
<h5 id="1-什么是flex布局"><strong>1. 什么是Flex布局？</strong> </h5>
<ul>
<li><strong>核心概念</strong>：一种一维布局模型，通过弹性容器（Flex Container）和弹性项目（Flex Item）实现灵活排列。</li>
<li><strong>优势</strong>：
<ul>
<li>无需浮动或定位即可实现复杂布局。</li>
<li>自动调整子元素大小以适应不同屏幕尺寸。</li>
</ul>
</li>
</ul>
<h5 id="2-基本用法"><strong>2. 基本用法</strong> </h5>
<ol>
<li>
<p><strong>定义Flex容器</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token selector"><span class="token class">.container</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span> <span class="token comment">/* 或 inline-flex */</span>
<span class="token punctuation">}</span>
</code></pre></li>
<li>
<p><strong>主轴与交叉轴</strong>：</p>
<ul>
<li><strong>主轴（Main Axis）</strong>：子元素的排列方向（默认水平）。</li>
<li><strong>交叉轴（Cross Axis）</strong>：垂直于主轴的方向。</li>
</ul>
<p><img src="https://css-tricks.com/wp-content/uploads/2018/10/flex-direction.svg" alt="Flex布局方向"></p>
</li>
</ol>
<h4 id="3-常用容器属性"><strong>3. 常用容器属性</strong> </h4>
<table>
<thead>
<tr>
<th>属性</th>
<th>作用</th>
<th>示例值</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>flex-direction</code></td>
<td>主轴方向</td>
<td><code>row</code>（默认）、<code>column</code></td>
</tr>
<tr>
<td><code>justify-content</code></td>
<td>主轴对齐方式</td>
<td><code>center</code>、<code>space-between</code></td>
</tr>
<tr>
<td><code>align-items</code></td>
<td>交叉轴对齐方式</td>
<td><code>center</code>、<code>flex-start</code></td>
</tr>
<tr>
<td><code>flex-wrap</code></td>
<td>是否换行</td>
<td><code>wrap</code>、<code>nowrap</code></td>
</tr>
</tbody>
</table>
<p><strong>示例</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token selector"><span class="token class">.container</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
  <span class="token property">flex-direction</span><span class="token punctuation">:</span> row<span class="token punctuation">;</span>     <span class="token comment">/* 水平排列 */</span>
  <span class="token property">justify-content</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token comment">/* 主轴居中 */</span>
  <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>     <span class="token comment">/* 交叉轴居中 */</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> <span class="token number">10</span><span class="token unit">px</span><span class="token punctuation">;</span>               <span class="token comment">/* 子元素间距 */</span>
<span class="token punctuation">}</span>
</code></pre><h5 id="4-常用子项属性"><strong>4. 常用子项属性</strong> </h5>
<table>
<thead>
<tr>
<th>属性</th>
<th>作用</th>
<th>示例值</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>flex</code></td>
<td>定义子项的伸缩比例</td>
<td><code>1</code>、<code>2 1 200px</code></td>
</tr>
<tr>
<td><code>order</code></td>
<td>调整子项显示顺序</td>
<td><code>2</code>（数值越大越靠后）</td>
</tr>
</tbody>
</table>
<p><strong>示例</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token selector"><span class="token class">.item1</span></span> <span class="token punctuation">{</span>
  <span class="token property">flex</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">;</span>  <span class="token comment">/* 占据剩余空间的1份 */</span>
<span class="token punctuation">}</span>
<span class="token selector"><span class="token class">.item2</span></span> <span class="token punctuation">{</span>
  <span class="token property">flex</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">;</span>  <span class="token comment">/* 占据剩余空间的2份 */</span>
<span class="token punctuation">}</span>
</code></pre><h5 id="5-应用场景pyqt5项目示例"><strong>5. 应用场景（PyQt5项目示例）</strong> </h5>
<ul>
<li>
<p><strong>考试列表水平居中</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token comment">/* 考试列表容器 */</span>
<span class="token selector">QWidget<span class="token id">#examList</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
  <span class="token property">flex-direction</span><span class="token punctuation">:</span> column<span class="token punctuation">;</span>  <span class="token comment">/* 垂直排列 */</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> <span class="token number">15</span><span class="token unit">px</span><span class="token punctuation">;</span>               <span class="token comment">/* 考试项间距 */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">20</span><span class="token unit">px</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></li>
<li>
<p><strong>学生签到界面布局</strong>：</p>
<pre data-role="codeBlock" data-info="css" class="language-css css"><code><span class="token comment">/* 签到界面：左侧摄像头区域，右侧信息区域 */</span>
<span class="token selector">QWidget<span class="token id">#signLayout</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
  <span class="token property">justify-content</span><span class="token punctuation">:</span> space-between<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></li>
</ul>
<hr>
<h4 id="总结"><strong>总结</strong> </h4>
<ol>
<li><strong>盒子模型</strong>：
<ul>
<li>理解 <code>content</code>、<code>padding</code>、<code>border</code>、<code>margin</code> 的关系。</li>
<li>使用 <code>box-sizing: border-box</code> 简化布局计算。</li>
</ul>
</li>
<li><strong>Flex布局</strong>：
<ul>
<li>通过 <code>display: flex</code> 定义容器。</li>
<li>掌握 <code>flex-direction</code>、<code>justify-content</code>、<code>align-items</code> 等核心属性。</li>
</ul>
</li>
<li><strong>PyQt5中的CSS支持</strong>：
<ul>
<li>部分属性可能与Web CSS不完全一致，需参考<a href="https://doc.qt.io/qt-5/stylesheet-syntax.html">Qt样式表文档</a>。</li>
</ul>
</li>
</ol>
<h3 id="总结-1"><strong>总结</strong> </h3>
<ul>
<li><strong>技术关联</strong>：Python作为核心语言，通过PyQt5实现界面，CSS美化样式，pymysql操作数据库，OOP和单例模式优化代码结构。</li>
<li><strong>项目侧重点</strong>：在论文中需强调人脸识别算法（<code>face_recognition</code>库）、PyQt5与CSS的界面交互设计、数据库的安全性与性能优化（如单例模式的应用）。</li>
</ul>
<hr>
<h3 id="一-根目录核心文件"><strong>一、根目录核心文件</strong> </h3>
<h4 id="1-mainpy"><strong>1. <code>main.py</code></strong> </h4>
<ul>
<li><strong>作用</strong>：程序入口文件，启动 PyQt5 应用并加载主窗口。</li>
<li><strong>示例代码</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-from">from</span> view<span class="token punctuation">.</span>login <span class="token keyword keyword-import">import</span> AppManager

<span class="token keyword keyword-if">if</span> __name__ <span class="token operator">==</span> <span class="token string">'__main__'</span><span class="token punctuation">:</span>
    app_manager <span class="token operator">=</span> AppManager<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 创建应用程序管理器</span>
    app_manager<span class="token punctuation">.</span>run<span class="token punctuation">(</span><span class="token punctuation">)</span>           <span class="token comment"># 启动应用程序</span>
</code></pre></li>
</ul>
<h4 id="2-gitignore"><strong>2. <code>.gitignore</code></strong> </h4>
<ul>
<li><strong>作用</strong>：指定 Git 版本控制忽略的文件（如缓存文件、本地配置）。</li>
<li><strong>常见忽略项</strong>：<code>__pycache__/</code>, <code>*.pyc</code>, <code>config/cache.json</code>（避免提交敏感数据）。</li>
</ul>
<hr>
<h3 id="二-核心文件夹解析"><strong>二、核心文件夹解析</strong> </h3>
<h4 id="1-components"><strong>1. <code>components/</code></strong> </h4>
<ul>
<li><strong>作用</strong>：存放可复用的自定义组件。</li>
<li><strong>文件示例</strong>：
<ul>
<li><code>messageBox.py</code>：自定义消息弹窗组件（如签到成功/失败提示）。</li>
</ul>
</li>
</ul>
<h4 id="2-config"><strong>2. <code>config/</code></strong> </h4>
<ul>
<li><strong>作用</strong>：存放系统配置和临时缓存文件。</li>
<li><strong>文件说明</strong>：
<ul>
<li><code>config.toml</code>：<strong>主配置文件</strong>，存储数据库连接参数（使用 TOML 格式）。<pre data-role="codeBlock" data-info="toml" class="language-toml toml"><code><span class="token punctuation">[</span><span class="token table class-name">database</span><span class="token punctuation">]</span>
<span class="token key property">host</span> <span class="token punctuation">=</span> <span class="token string">"localhost"</span>
<span class="token key property">user</span> <span class="token punctuation">=</span> <span class="token string">"root"</span>
<span class="token key property">password</span> <span class="token punctuation">=</span> <span class="token string">"123456"</span>
</code></pre></li>
<li><code>cache.json</code>：<strong>临时缓存文件</strong>，存储用户登录状态。</li>
</ul>
</li>
</ul>
<h4 id="3-dao-data-access-object"><strong>3. <code>dao/</code> (Data Access Object)</strong> </h4>
<ul>
<li><strong>作用</strong>：数据访问层，封装数据库操作。</li>
<li><strong>文件说明</strong>：
<ul>
<li><code>classorm.py</code>：可能定义 ORM（对象关系映射）模型类（如 <code>Exam</code>、<code>Student</code>）。</li>
<li><code>classRecord.py</code>：处理课程或考试记录的增删改查。</li>
<li><code>orm.py</code>：通用数据库操作工具（如连接池管理、SQL 执行）。</li>
<li><code>exam.py</code>：考试相关的数据库操作（如发布考试、查询考试列表）。</li>
</ul>
</li>
</ul>
<h4 id="4-static"><strong>4. <code>static/</code></strong> </h4>
<ul>
<li><strong>作用</strong>：存放静态资源文件（如图标、背景图、CSS 样式表）。</li>
</ul>
<h4 id="5-utils"><strong>5. <code>utils/</code></strong> </h4>
<ul>
<li><strong>作用</strong>：工具类模块，提供通用功能。</li>
<li><strong>文件说明</strong>：
<ul>
<li><code>recognition.py</code>：人脸识别核心逻辑（调用 <code>face_recognition</code> 库）。</li>
<li><code>time.py</code>：时间格式化工具（如将时间戳转为 <code>YYYY-MM-DD</code>）。</li>
<li><code>toml.py</code>：解析 <code>config.toml</code> 文件的工具。</li>
<li><code>json.py</code>：读写 <code>cache.json</code> 的工具。</li>
</ul>
</li>
</ul>
<h4 id="6-view"><strong>6. <code>view/</code></strong> </h4>
<ul>
<li><strong>作用</strong>：存放所有 <strong>界面窗口类</strong>，每个文件对应一个 PyQt5 窗口或对话框。</li>
<li><strong>文件说明</strong>：
<ul>
<li><code>login.py</code>：登录界面（输入账号密码）。</li>
<li><code>dashboard.py</code>：教师主控制面板（发布考试、查看签到记录）。</li>
<li><code>studenthome.py</code>：学生主页（显示待签到考试列表）。</li>
<li><code>studentprofile.py</code>：学生信息详情页。</li>
<li><code>stuHistory.py</code>：学生历史签到记录页。</li>
<li><code>auth.py</code>：身份认证逻辑（如登录验证）。</li>
</ul>
</li>
</ul>
<h4><strong>7. <code>__pycache__/</code></strong> {#7-<strong>pycache</strong> }</h4>
<ul>
<li><strong>作用</strong>：Python 编译生成的字节码缓存文件（自动生成，无需手动修改）。</li>
</ul>
<hr>
<h3 id="三-关键文件详细说明"><strong>三、关键文件详细说明</strong> </h3>
<h4 id="1-viewhomepy"><strong>1. <code>view/home.py</code></strong> </h4>
<ul>
<li><strong>作用</strong>：系统主窗口，根据用户角色（教师/学生）加载不同子界面。</li>
<li><strong>代码示例</strong>：<pre data-role="codeBlock" data-info="python" class="language-python python"><code><span class="token keyword keyword-from">from</span> PyQt5<span class="token punctuation">.</span>QtWidgets <span class="token keyword keyword-import">import</span> QMainWindow
<span class="token keyword keyword-from">from</span> view<span class="token punctuation">.</span>dashboard <span class="token keyword keyword-import">import</span> TeacherDashboard  <span class="token comment"># 教师仪表盘</span>
<span class="token keyword keyword-from">from</span> view<span class="token punctuation">.</span>studenthome <span class="token keyword keyword-import">import</span> StudentHome    <span class="token comment"># 学生主页</span>

<span class="token keyword keyword-class">class</span> <span class="token class-name">HomeWindow</span><span class="token punctuation">(</span>QMainWindow<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword keyword-def">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> user_role<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token builtin">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>__init__<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword keyword-if">if</span> user_role <span class="token operator">==</span> <span class="token string">"teacher"</span><span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>setCentralWidget<span class="token punctuation">(</span>TeacherDashboard<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword keyword-else">else</span><span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>setCentralWidget<span class="token punctuation">(</span>StudentHome<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></li>
</ul>
<p>举个例子，这里当然不是这样干的，不过你可以写到论文中。</p>
<h4 id="2-daoexampy"><strong>2. <code>dao/exam.py</code></strong> </h4>
<ul>
<li><strong>作用</strong>：处理考试数据的数据库操作。</li>
</ul>
<hr>
<h3 id="四-项目结构优点"><strong>四、项目结构优点</strong> </h3>
<hr>
<h4 id="模块化设计职责清晰"><strong>模块化设计，职责清晰</strong> </h4>
<ul>
<li><strong>优势</strong>：每个文件夹/文件专注于单一功能，便于定位代码。
<ul>
<li><strong>示例</strong>：
<ul>
<li><code>view/</code> 只管理界面逻辑（如登录窗口、考试列表）。</li>
<li><code>dao/</code> 只处理数据库操作（如查询考试、写入签到记录）。</li>
<li><code>utils/</code> 提供通用工具（如人脸识别、时间格式化）。</li>
</ul>
</li>
<li><strong>好处</strong>：开发时快速定位功能模块，减少代码混乱。</li>
</ul>
</li>
</ul>
<h4 id="高可维护性"><strong>高可维护性</strong> </h4>
<ul>
<li><strong>优势</strong>：修改或扩展功能时，只需改动特定模块，避免“牵一发而动全身”。
<ul>
<li><strong>示例</strong>：
<ul>
<li>修改数据库表结构时，只需调整 <code>dao/</code> 中的 ORM 模型和 SQL 语句，无需改动界面代码。</li>
<li>更换人脸识别算法时，只需修改 <code>utils/recognition.py</code>，不影响其他模块。</li>
</ul>
</li>
<li><strong>好处</strong>：降低维护成本，减少引入新 Bug 的风险。</li>
</ul>
</li>
</ul>
<h4 id="便于团队协作"><strong>便于团队协作</strong> </h4>
<ul>
<li><strong>优势</strong>：分工明确，多人协作互不干扰。
<ul>
<li><strong>示例</strong>：
<ul>
<li>前端开发者专注 <code>view/</code> 和 <code>static/</code>（界面设计与美化）。</li>
<li>后端开发者专注 <code>dao/</code> 和 <code>utils/</code>（数据库与算法逻辑）。</li>
</ul>
</li>
<li><strong>好处</strong>：并行开发，提升效率。</li>
</ul>
</li>
</ul>
<h4 id="配置与代码分离"><strong>配置与代码分离</strong> </h4>
<ul>
<li><strong>优势</strong>：动态配置参数集中管理，避免硬编码。
<ul>
<li><strong>示例</strong>：
<ul>
<li><code>config/config.toml</code> 存储数据库连接、人脸识别阈值等参数。</li>
<li><code>config/cache.json</code> 缓存临时数据（如用户登录状态）。</li>
</ul>
</li>
<li><strong>好处</strong>：修改配置无需重新编译代码，适应不同环境（开发/生产）。</li>
</ul>
</li>
</ul>
<h4 id="资源统一管理"><strong>资源统一管理</strong> </h4>
<ul>
<li><strong>优势</strong>：静态资源（如图片、样式表）集中存放，避免路径混乱。
<ul>
<li><strong>示例</strong>：
<ul>
<li><code>static/</code> 存放系统图标、默认头像等，界面通过统一路径引用。</li>
</ul>
</li>
<li><strong>好处</strong>：资源修改和替换更方便。</li>
</ul>
</li>
</ul>
<h4 id="易于测试与调试"><strong>易于测试与调试</strong> </h4>
<ul>
<li><strong>优势</strong>：模块独立，可单独测试。
<ul>
<li><strong>示例</strong>：
<ul>
<li>测试人脸识别准确性时，直接运行 <code>utils/recognition.py</code> 的单元测试。</li>
<li>调试数据库操作时，单独调用 <code>dao/exam.py</code> 的方法。</li>
</ul>
</li>
<li><strong>好处</strong>：快速定位问题，提升代码质量。</li>
</ul>
</li>
</ul>
<h4 id="代码复用性强"><strong>代码复用性强</strong> </h4>
<ul>
<li><strong>优势</strong>：通用模块可被多场景复用。
<ul>
<li><strong>示例</strong>：
<ul>
<li><code>components/messageBox.py</code> 自定义弹窗，可在教师端和学生端共用。</li>
<li><code>utils/time.py</code> 提供时间处理工具，所有模块均可调用。</li>
</ul>
</li>
<li><strong>好处</strong>：减少重复代码，提升开发效率。</li>
</ul>
</li>
</ul>
<h4 id="符合软件工程规范"><strong>符合软件工程规范</strong> </h4>
<ul>
<li><strong>优势</strong>：标准的项目结构便于他人快速理解代码。
<ul>
<li><strong>示例</strong>：
<ul>
<li>开发者看到 <code>view/</code> 即知是界面层，看到 <code>dao/</code> 即知是数据层。</li>
<li><code>.gitignore</code> 规范版本控制，避免提交无用文件。</li>
</ul>
</li>
<li><strong>好处</strong>：提升代码可读性，方便后续交接或开源。</li>
</ul>
</li>
</ul>
<h4 id="优点总结"><strong>优点总结</strong> </h4>
<ul>
<li><strong>对开发者</strong>：减少心智负担，提升开发效率。</li>
<li><strong>对项目</strong>：增强健壮性，降低长期维护成本。</li>
<li><strong>对毕业设计</strong>：清晰的结构能更好地展示你的技术设计能力，让答辩老师一目了然！</li>
</ul>
<hr>
<h3 id="五-总结与设计思路"><strong>五、总结与设计思路</strong> </h3>
<ol>
<li><strong>模块化设计</strong>：
<ul>
<li><code>view/</code> 分离界面逻辑，<code>dao/</code> 分离数据操作，<code>utils/</code> 提供通用工具，符合 <strong>MVC 模式</strong>。</li>
</ul>
</li>
<li><strong>配置与数据分离</strong>：
<ul>
<li>使用 <code>config.toml</code> 管理动态配置，<code>cache.json</code> 存储临时状态，避免硬编码。</li>
</ul>
</li>
</ol>
<p>通过此结构，项目实现了高内聚低耦合（<br>
高内聚：一个模块（如类、函数、文件）内部的功能高度相关，专注于完成单一职责。<br>
低耦合：模块之间的依赖关系尽可能少，修改一个模块时不影响其他模块。<br>
优点：<br>
· 易维护：修改一个模块时，无需担心“蝴蝶效应”。<br>
· 易扩展：新增功能只需添加新模块，而非重构旧代码。<br>
· 易测试：模块可独立测试（如单独测试人脸识别逻辑）。<br>
）。</p>
<h2 id="环境要求">环境要求 </h2>
<ul>
<li>Python3.11.x</li>
</ul>

      </div>
      
      
    
    
    
    
    
    
  
    </body></html>